﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace LaravelSession
{
    public class Program
    {
        static readonly Dictionary<string, string> sessionDict = new()
        {
            {"iv", @"PEGE6zj6C\/VdOmnwVXSFaw==".Replace(@"\", "")},
            {"value", @"fpKlXI2Sa1fq8mDIgwvBr1g235LvExcde8IZ0JY9Jw5DN3IArBQ\/2ghmU21yjReOLC84DBpkaIwcghwAorVPYg==".Replace(@"\", "")},
            {"mac", @"366d20bf35f7a4123f97659b3be8b1083eb15ffd29567b9699c220a5a6a00e95"}
        };

        public static void Main(string[] args)
        {
            const string key = "hmlGQefo7whnF6o2GCm3iyM9hgPWziRP";

            var sw = Stopwatch.StartNew();
            var ivBase64 = Convert.FromBase64String(sessionDict["iv"]);
            var result = DecryptStringFromBytes_Aes(
                Convert.FromBase64String(sessionDict["value"]),
                Encoding.UTF8.GetBytes(key),
                ivBase64);

            Console.WriteLine($"{result} {sw.Elapsed}");
            Console.ReadKey();
        }

        static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] key, byte[] iv)
        {
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException(nameof(cipherText));
            if (key == null || key.Length <= 0)
                throw new ArgumentNullException(nameof(key));
            if (iv == null || iv.Length <= 0)
                throw new ArgumentNullException(nameof(iv));

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = key;
                aesAlg.IV = iv;
                aesAlg.Mode = CipherMode.CBC;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption.
                using var msDecrypt = new MemoryStream(cipherText);
                using var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
                using var srDecrypt = new StreamReader(csDecrypt);
                plaintext = srDecrypt.ReadToEnd();
            }

            return plaintext;
        }
    }
}
